package com.net.Thread;

class Test1 implements Runnable
{
   Object obj1;
   Object obj2;
   
   Test1(Object obj1, Object obj2)
   {
	   this.obj1 = obj1;
	   this.obj2 = obj2;
   }
	
	@Override
	public void run() 
	{
		String name = Thread.currentThread().getName();
		System.out.println(name +" aquiring lock on " +obj1);
		synchronized (obj1)
		{
			System.out.println(name + " aquired lock on "+obj2);
			work();
		}
		System.out.println(name + " released the lock "+obj1);
		
		System.out.println(name + " aquiring the lock " + obj2);
		
		synchronized (obj2)
		{
			System.out.println(name + " aquired the lock " + obj2);
			work();
		}
		System.out.println(name + " released the lock " +obj2);
	}

	private void work()  
	{
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}





public class AvoidDeadLock
{

	public static void main(String[] args) throws InterruptedException
	{
		Object obj1 = new Object();
		Object obj2 = new Object();
		Object obj3 = new Object();
		
		Thread t1 = new Thread(new Test1(obj1,obj2), "t1");
		Thread t2 = new Thread(new Test1(obj1,obj3), "t2");
		Thread t3 = new Thread(new Test1(obj2,obj3), "t3");
		
		t1.start();
		Thread.sleep(5000);
		
		t2.start();
		Thread.sleep(5000);
		
		t3.start();
		
		
		

	}

}
